﻿using System;
using Mbs.Collections;
using Mbs.ComponentModel.Container.Lifestyle;
using Mbs.Reflection;
using Mbs.ComponentModel.Container.Fluent;

namespace Mbs
{
    public static class FluentExtensions
    {

        private static void Register(IServiceRegistry kernel, Action<IBindingExpression> handler)
        {
            if (handler == null)
                throw new ArgumentNullException("handler == null");

            var component = new ComponentExpression { Registry = kernel };
            handler(component);

            if (component.Implementation == null && component.Factory == null)
                throw new ArgumentNullException("Implementation == null && Factory ==null");

            if (string.IsNullOrEmpty(component.Id))
            {
                if (component.Implementation != null)
                    component.Id = component.Implementation.FullName;
                else
                    component.Id = component.Factory.ToString() + "/" + component.Service.FullName;
            }

            if (component.Service == null)
            {
                if (component.Implementation != null)
                    component.Service = component.Implementation;
            }

            if (component.Service != null && component.Service.IsOpenGenericType())
                component.Lifestyle = GetGenericLifestyle(component.Lifestyle);

            kernel.Register(component);
        }

        private static string GetGenericLifestyle(string lifestyle)
        {
            if (string.Equals(lifestyle, LifestyleType.Singleton, StringComparison.OrdinalIgnoreCase))
                return LifestyleType.GenericSingleton;
            if (string.Equals(lifestyle, LifestyleType.Transient, StringComparison.OrdinalIgnoreCase))
                return LifestyleType.GenericTransient;
            return lifestyle;
        }

        public static IServiceRegistry Register(this IServiceRegistry kernel, params Action<IBindingExpression>[] handlers)
        {
            if (handlers != null && handlers.Length > 0)
                handlers.Foreach(exp => Register(kernel, exp));
            return kernel;
        }

        public static IFactoryExpression Singleton(this IFactoryExpression exp)
        {
            return exp.Lifestyle(LifestyleType.Singleton);
        }

        public static IImplementationExpression Singleton(this IImplementationExpression exp)
        {
            return exp.Lifestyle(LifestyleType.Singleton);
        }

        public static IFactoryExpression Transient(this IFactoryExpression exp)
        {
            return exp.Lifestyle(LifestyleType.Transient);
        }

        public static IImplementationExpression Transient(this IImplementationExpression exp)
        {
            return exp.Lifestyle(LifestyleType.Transient);
        }

    }
}
